﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Shapes;

namespace ProtoXaml
{
    public class WigglyBorder : Border
    {
        const double step = 8;
        const double delta = 2;
        const double cornersteps = 10;

        public WigglyBorder() : base()
        {
            //Random rand = new Random((int)DateTime.Now.Ticks);
            //_seed = rand.Next(); 
            _seed = (int)DateTime.Now.Ticks;
        }
        int _seed = 0;
        
        delegate double GetDouble();

        protected override void OnRender(DrawingContext dc)
        {
            Random rand = new Random(_seed);
            GetDouble Delta = delegate() { return rand.NextDouble() * delta; };   

            Rect bounds = new Rect(0, 0, ActualWidth, ActualHeight);
            PathFigure pf = new PathFigure();
        
            if (this.CornerRadius.TopLeft > 3)
            {
                double r;
                r = this.CornerRadius.TopLeft;
                for (double a = 0; a < Math.PI / 2; a += Math.PI / cornersteps)
                    pf.Segments.Add(new LineSegment(new Point(bounds.Left + r - Math.Cos(a) * r + Delta(), bounds.Top + r - Math.Sin(a) * r + Delta()), true));
                for (double x = r; x < this.ActualWidth - r; x += step)
                    pf.Segments.Add(new LineSegment(new Point(x, bounds.Top + Delta()), true));

                for (double a = 0; a < Math.PI / 2; a += Math.PI / cornersteps)
                    pf.Segments.Add(new LineSegment(new Point(bounds.Right - r + Math.Sin(a) * r + Delta(), bounds.Top + r - Math.Cos(a) * r + Delta()), true));
                for (double y = r; y < this.ActualHeight-r; y += step)
                    pf.Segments.Add(new LineSegment(new Point(bounds.Right + Delta(), y), true));

                for (double a = 0; a < Math.PI / 2; a += Math.PI / cornersteps)
                    pf.Segments.Add(new LineSegment(new Point(bounds.Right - r + Math.Cos(a) * r + Delta(), bounds.Bottom - r + Math.Sin(a) * r + Delta()), true));
                for (double x = this.ActualWidth-r; x >= r; x -= step)
                    pf.Segments.Add(new LineSegment(new Point(x, bounds.Bottom + Delta()), true));

                for (double a = 0; a < Math.PI / 2; a += Math.PI / cornersteps)
                    pf.Segments.Add(new LineSegment(new Point(bounds.Left + r - Math.Sin(a) * r + Delta(), bounds.Bottom - r + Math.Cos(a) * r + Delta()), true));
                for (double y = this.ActualHeight-r; y >= r; y -= step)
                    pf.Segments.Add(new LineSegment(new Point(bounds.Left + Delta(), y), true));
            }
            else
            {
                for (double x = 0; x < this.ActualWidth; x += step)
                    pf.Segments.Add(new LineSegment(new Point(x, bounds.Top + Delta()), true));
                for (double y = 0; y < this.ActualHeight; y += step)
                    pf.Segments.Add(new LineSegment(new Point(bounds.Right + Delta(), y), true));
                for (double x = this.ActualWidth; x >= 0; x -= step)
                    pf.Segments.Add(new LineSegment(new Point(x, bounds.Bottom + Delta()), true));
                for (double y = this.ActualHeight; y >= 0; y -= step)
                    pf.Segments.Add(new LineSegment(new Point(bounds.Left + Delta(), y), true));
            }
            pf.StartPoint = ((LineSegment)pf.Segments[0]).Point;
            pf.IsClosed = true;


            PathGeometry pg = new PathGeometry(new PathFigure[] { pf });
            if (this.BorderBrush == null) 
                this.BorderBrush = Brushes.Black;
            Pen pen = new Pen(this.BorderBrush, this.BorderThickness.Left);
            Drawing d = new GeometryDrawing(this.Background, pen, pg);

            dc.DrawDrawing(d);
        }

        private static StreamGeometry StreamGeometryFromString(string geometry)
        {
            GeometryConverter c = new GeometryConverter();
            return (StreamGeometry)c.ConvertFromString(geometry);
        }
    }


    public class WigglyLine : Shape
    {
        const double step = 8;
        const double delta = 2;
        const double cornersteps = 10;

        public WigglyLine()
            : base()
        {
            Random rand = new Random((int)DateTime.Now.Ticks);
            _seed = rand.Next();
        }

        int _seed = 0;

        delegate double GetDouble();

        protected override Geometry DefiningGeometry
        {
            get
            {

                Random rand = new Random(_seed);
                GetDouble Delta = delegate() { return rand.NextDouble() * delta; };

                Rect bounds = new Rect(0, 0, ActualWidth, ActualHeight);
                PathFigure pf = new PathFigure();

                if (ActualWidth > 0)
                {
                    for (double x = 0; x < this.ActualWidth; x += step)
                        pf.Segments.Add(new LineSegment(new Point(x, bounds.Top + Delta()), true));
                    //for (double y = 0; y < this.ActualHeight; y += step)
                    //    pf.Segments.Add(new LineSegment(new Point(bounds.Right + Delta(), y), true));
                    //for (double x = this.ActualWidth; x >= 0; x -= step)
                    //    pf.Segments.Add(new LineSegment(new Point(x, bounds.Bottom + Delta()), true));
                    //for (double y = this.ActualHeight; y >= 0; y -= step)
                    //    pf.Segments.Add(new LineSegment(new Point(bounds.Left + Delta(), y), true));

                    pf.StartPoint = ((LineSegment)pf.Segments[0]).Point;
                    pf.IsClosed = true;

                }

                PathGeometry pg = new PathGeometry(new PathFigure[] { pf });
                //if (this.BorderBrush == null)
                //    this.BorderBrush = Brushes.Black;
                //Pen pen = new Pen(this.BorderBrush, this.BorderThickness.Left);
                //Drawing d = new GeometryDrawing(this.Background, pen, pg);

                return pg;
            }
        }

        private static StreamGeometry StreamGeometryFromString(string geometry)
        {
            GeometryConverter c = new GeometryConverter();
            return (StreamGeometry)c.ConvertFromString(geometry);
        }
    }

}
